package cn.HuanG.org.aop;

import cn.HuanG.annotation.OtherLog;
import cn.HuanG.org.domain.OtherLogEntity;
import cn.HuanG.org.service.IOtherLogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

/**
 *
 * <p>AOP日志切面类<p>
 *  * @author
 * */
@Aspect
@Component
@Order(3)
public class OtherLogAop {
    @Autowired
    private IOtherLogService otherLogService;
    /**
     * 环绕通知记录日志通过注解匹配到需要增加日志功能的方法
     *
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("@annotation(cn.HuanG.annotation.OtherLog)")
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
        // 1.方法执行前的处理，相当于前置通知
        // 获取方法签名
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        // 获取类名
        String class_name = pjp.getTarget().getClass().getName();
        // 获取方法
        Method method = methodSignature.getMethod();
        // 获取请求参数
        String params = Arrays.toString(pjp.getArgs()).replace("[", "")
                .replace("]", "");
        // 获取方法上面的注解
        OtherLog otherLogAop = method.getAnnotation(OtherLog.class);
        // 获取操作描述的属性值
        String name = otherLogAop.logName();
        // 创建一个日志对象(准备记录日志)
        OtherLogEntity log = new OtherLogEntity();
        log.setName(name);
        log.setMethod(method.getName());
        log.setParams(params);
        try {
            log.setIp(Inet4Address.getLocalHost().toString());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        Object result = null;
        try {
            // 让代理方法执行
            result = pjp.proceed();
            // 2.相当于后置通知(方法成功执行之后走这里)
            log.setSucceed("成功");// 设置操作结果
        } catch (SQLException e) {
            // 3.相当于异常通知部分
            log.setSucceed("失败");// 设置操作结果
        } finally {
            // 4.相当于最终通知
            log.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));// 设置操作日期
            // 打印日志记录
            System.out.println(log.toString());
            // 在此处直接调用service插入数据库也可以。
            otherLogService.save(log);
            // 也可以学习guns一样利用线程池进行日志存储。
        }
        return result;
    }
}

